package core

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"chainmaker.org/chainmaker/common/v2/crypto"
	"chainmaker.org/chainmaker/common/v2/crypto/asym"
	"chainmaker.org/chainmaker/pb-go/v2/accesscontrol"
	"chainmaker.org/chainmaker/pb-go/v2/api"
	"chainmaker.org/chainmaker/pb-go/v2/common"
	"github.com/gogo/protobuf/proto"
	"google.golang.org/grpc"
)

// RpcNodeClient 简化的RPC客户端接口
type RpcNodeClient interface {
	SendRequest(ctx context.Context, request *common.TxRequest) (*common.TxResponse, error)
}

// GRPCClient 实现RpcNodeClient接口的gRPC客户端
// 修改：client字段类型为api.RpcNodeClient
// 并在SendRequest中调用真实gRPC方法
type GRPCClient struct {
	conn   *grpc.ClientConn
	client api.RpcNodeClient
}

// SendRequest 发送请求
func (c *GRPCClient) SendRequest(ctx context.Context, request *common.TxRequest) (*common.TxResponse, error) {
	// 真实调用链节点
	return c.client.SendRequest(ctx, request)
}

// ChainClient 链客户端
type ChainClient struct {
	ChainID   string
	NodeAddr  string
	NodePort  int
	conn      *grpc.ClientConn
	rpcClient RpcNodeClient
}

// ContractResult 合约调用结果
type ContractResult struct {
	TxID    string      `json:"tx_id"`
	Code    int32       `json:"code"`
	Message string      `json:"message"`
	Result  interface{} `json:"result,omitempty"`
}

// NewChainClient 创建链客户端
func NewChainClient(chainID, nodeAddr string, nodePort int) (*ChainClient, error) {
	fmt.Printf("[DEBUG] 创建ChainClient: chainID=%s, nodeAddr=%s, nodePort=%d\n", chainID, nodeAddr, nodePort)
	// 创建 gRPC 连接
	conn, err := grpc.Dial(
		fmt.Sprintf("%s:%d", nodeAddr, nodePort),
		grpc.WithInsecure(),
	)
	if err != nil {
		fmt.Printf("[ERROR] 连接gRPC失败: %v\n", err)
		return nil, fmt.Errorf("failed to connect: %v", err)
	}

	fmt.Println("[DEBUG] gRPC连接创建成功")
	// 创建真正的 gRPC 客户端
	client := &GRPCClient{
		conn:   conn,
		client: api.NewRpcNodeClient(conn),
	}

	return &ChainClient{
		ChainID:   chainID,
		NodeAddr:  nodeAddr,
		NodePort:  nodePort,
		conn:      conn,
		rpcClient: client,
	}, nil
}

// Close 关闭连接
func (c *ChainClient) Close() {
	if c.conn != nil {
		c.conn.Close()
	}
}

// Query 查询合约
func (c *ChainClient) Query(contractName, method, privateKey string, params map[string]string) (*ContractResult, error) {
	return c.invokeContract(common.TxType_QUERY_CONTRACT, contractName, method, privateKey, params)
}

// Invoke 调用合约
func (c *ChainClient) Invoke(contractName, method, privateKey string, params map[string]string) (*ContractResult, error) {
	return c.invokeContract(common.TxType_INVOKE_CONTRACT, contractName, method, privateKey, params)
}

// invokeContract 调用合约通用方法
func (c *ChainClient) invokeContract(txType common.TxType, contractName, method, privateKey string, params map[string]string) (*ContractResult, error) {
	fmt.Printf("[DEBUG] invokeContract: txType=%v, contractName=%s, method=%s\n", txType, contractName, method)
	fmt.Printf("[DEBUG] 参数: params=%v\n", params)
	// 解析私钥
	priv, err := asym.PrivateKeyFromPEM([]byte(privateKey), nil)
	if err != nil {
		fmt.Printf("[ERROR] 解析私钥失败: %v\n", err)
		return nil, fmt.Errorf("failed to parse private key: %v", err)
	}

	// 获取公钥
	pub := priv.PublicKey()
	pubKeyPEM, err := pub.String()
	if err != nil {
		fmt.Printf("[ERROR] 获取公钥PEM失败: %v\n", err)
		return nil, fmt.Errorf("failed to get public key PEM: %v", err)
	}
	fmt.Printf("[DEBUG] 公钥PEM: %s\n", pubKeyPEM)

	// 转换参数
	kvs := make([]*common.KeyValuePair, 0, len(params))
	for k, v := range params {
		fmt.Printf("[DEBUG] 参数对: %s=%s\n", k, v)
		kvs = append(kvs, &common.KeyValuePair{
			Key:   k,
			Value: []byte(v),
		})
	}

	// 创建交易ID
	txID := generateTxID()
	fmt.Printf("[DEBUG] 生成交易ID: %s\n", txID)

	// 创建payload
	payload := &common.Payload{
		ChainId:      c.ChainID,
		TxType:       txType,
		TxId:         txID,
		Timestamp:    time.Now().Unix(),
		ContractName: contractName,
		Method:       method,
		Parameters:   kvs,
	}
	fmt.Printf("[DEBUG] 构造Payload: %+v\n", payload)

	// 签名 - 使用proto.Marshal(payload)保证与链节点一致
	payloadBytes, err := proto.Marshal(payload)
	if err != nil {
		fmt.Printf("[ERROR] proto.Marshal payload失败: %v\n", err)
		return nil, fmt.Errorf("failed to marshal payload: %v", err)
	}
	fmt.Printf("[DEBUG] Payload字节: %x\n", payloadBytes)

	// 根据算法类型选择哈希算法
	var hashType crypto.HashType
	switch priv.Type() {
	case crypto.SM2:
		hashType = crypto.HASH_TYPE_SM3
	case crypto.ECC_NISTP256:
		hashType = crypto.HASH_TYPE_SHA256
	default:
		hashType = crypto.HASH_TYPE_SHA256
	}
	fmt.Printf("[DEBUG] 使用哈希算法: %v\n", hashType)

	opts := crypto.SignOpts{
		Hash: hashType,
		UID:  crypto.CRYPTO_DEFAULT_UID,
	}

	signature, err := priv.SignWithOpts(payloadBytes, &opts)
	if err != nil {
		fmt.Printf("[ERROR] 签名失败: %v\n", err)
		return nil, fmt.Errorf("failed to sign payload: %v", err)
	}
	fmt.Printf("[DEBUG] 签名: %x\n", signature)

	// 构造请求
	req := &common.TxRequest{
		Payload: payload,
		Sender: &common.EndorsementEntry{
			Signer: &accesscontrol.Member{
				OrgId:      "", // 组织ID可为空
				MemberInfo: []byte(pubKeyPEM),
				MemberType: accesscontrol.MemberType_PUBLIC_KEY,
			},
			Signature: signature,
		},
	}
	fmt.Printf("[DEBUG] 构造TxRequest: %+v\n", req)

	// 发送请求
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	fmt.Println("[DEBUG] 发送请求...")
	resp, err := c.rpcClient.SendRequest(ctx, req)
	if err != nil {
		fmt.Printf("[ERROR] 发送请求失败: %v\n", err)
		return nil, fmt.Errorf("failed to send request: %v", err)
	}
	fmt.Printf("[DEBUG] 收到响应: %+v\n", resp)

	// 处理结果
	result := &ContractResult{
		TxID:    resp.TxId,
		Code:    int32(resp.Code),
		Message: resp.Message,
	}

	// 如果有合约执行结果
	if resp.ContractResult != nil && len(resp.ContractResult.Result) > 0 {
		fmt.Printf("[DEBUG] 合约执行结果原始数据: %s\n", string(resp.ContractResult.Result))
		// 尝试解析为JSON
		var jsonResult interface{}
		if err := json.Unmarshal(resp.ContractResult.Result, &jsonResult); err == nil {
			fmt.Printf("[DEBUG] 合约执行结果解析为JSON: %+v\n", jsonResult)
			result.Result = jsonResult
		} else {
			fmt.Printf("[WARN] 合约执行结果不是JSON: %v\n", err)
			// 如果不是JSON，则作为字符串返回
			result.Result = string(resp.ContractResult.Result)
		}
	}

	fmt.Printf("[DEBUG] 最终返回结果: %+v\n", result)
	return result, nil
}

// 生成交易ID
func generateTxID() string {
	return fmt.Sprintf("%d", time.Now().UnixNano())
}

// 系统合约常量
const (
	SysContractCert        = "CERT_MANAGE"
	SysContractChainConfig = "CHAIN_CONFIG"
	SysContractAccount     = "ACCOUNT_MANAGER"
)

// 系统合约方法常量
const (
	// 证书管理合约方法
	SysMethodCertAdd    = "CERT_ADD"
	SysMethodCertDelete = "CERT_DELETE"
	SysMethodCertQuery  = "CERT_QUERY"

	// 链配置合约方法
	SysMethodChainConfigQuery = "GET_CHAIN_CONFIG"
	SysMethodBlockHeightQuery = "GET_BLOCK_HEIGHT"
	SysMethodBlockInfoQuery   = "GET_BLOCK_BY_HEIGHT"
	SysMethodTxQuery          = "GET_TX_BY_TX_ID"

	// 账户管理合约方法
	SysMethodAccountAdd    = "ACCOUNT_ADD"
	SysMethodAccountDelete = "ACCOUNT_DELETE"
	SysMethodAccountQuery  = "ACCOUNT_QUERY"
)
